package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.mapper.PublisherMapper;
import com.zenithmind.library.mapper.PublisherStatisticsMapper;
import com.zenithmind.library.pojo.domain.Publisher;
import com.zenithmind.library.pojo.domain.PublisherStatistics;
import com.zenithmind.library.pojo.dto.PublisherCreateDTO;
import com.zenithmind.library.pojo.dto.PublisherUpdateDTO;
import com.zenithmind.library.pojo.query.PublisherQuery;
import com.zenithmind.library.pojo.vo.PublisherVO;
import com.zenithmind.library.service.PublisherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 出版社服务实现类
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PublisherServiceImpl extends ServiceImpl<PublisherMapper, Publisher> implements PublisherService {

    private final PublisherMapper publisherMapper;
    private final PublisherStatisticsMapper publisherStatisticsMapper;
    private final BookMapper bookMapper;

    @Override
    @Cacheable(value = "publishers", key = "'page:' + #query.hashCode()")
    public PageResult<PublisherVO> getPublisherPage(PublisherQuery query) {
        log.info("分页查询出版社，查询条件：{}", query);

        Page<PublisherVO> page = query.toPage();
        IPage<PublisherVO> result = publisherMapper.selectPublisherPage(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "publishers", key = "'detail:' + #id")
    public PublisherVO getPublisherDetail(String id) {
        log.info("查询出版社详情，ID：{}", id);
        
        Publisher publisher = getById(id);
        if (publisher == null) {
            throw new RuntimeException("出版社不存在");
        }
        
        return convertToVO(publisher);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<PublisherVO> createPublisher(PublisherCreateDTO createDTO) {
        log.info("创建出版社，数据：{}", createDTO);
        
        // 检查出版社编码是否已存在
        if (StringUtils.hasText(createDTO.getCode()) && 
            existsByCode(createDTO.getCode(), null)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社编码已存在", null);
        }
        
        // 检查出版社名称是否已存在
        if (existsByName(createDTO.getName(), null)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社名称已存在", null);
        }
        
        // 转换为实体对象
        Publisher publisher = new Publisher();
        BeanUtils.copyProperties(createDTO, publisher);
        
        publisher.setStatus(1); // 默认启用
        // 注意：图书数量现在由PublisherStatistics实体管理 // 初始图书数量为0
        publisher.setCreateTime(LocalDateTime.now());
        publisher.setUpdateTime(LocalDateTime.now());
        
        // 保存出版社
        boolean saved = save(publisher);
        if (!saved) {
            return Result.fail(ResultCode.FAIL.getCode(), "创建出版社失败", null);
        }
        
        // 返回创建的出版社信息
        PublisherVO publisherVO = convertToVO(publisher);
        return Result.success(publisherVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<PublisherVO> updatePublisher(String id, PublisherUpdateDTO updateDTO) {
        log.info("更新出版社，ID：{}，数据：{}", id, updateDTO);
        
        // 检查出版社是否存在
        Publisher existingPublisher = getById(id);
        if (existingPublisher == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在", null);
        }
        
        // 检查出版社编码是否已被其他出版社使用
        if (StringUtils.hasText(updateDTO.getCode()) && 
            existsByCode(updateDTO.getCode(), id)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社编码已被其他出版社使用", null);
        }
        
        // 检查出版社名称是否已被其他出版社使用
        if (StringUtils.hasText(updateDTO.getName()) && 
            existsByName(updateDTO.getName(), id)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社名称已被其他出版社使用", null);
        }
        
        // 更新出版社信息
        Publisher publisher = new Publisher();
        BeanUtils.copyProperties(updateDTO, publisher);
        publisher.setId(id);
        publisher.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(publisher);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社失败", null);
        }
        
        // 返回更新后的出版社信息
        Publisher updatedPublisher = getById(id);
        PublisherVO publisherVO = convertToVO(updatedPublisher);
        return Result.success(publisherVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> deletePublisher(String id) {
        log.info("删除出版社，ID：{}", id);
        
        // 检查出版社是否存在
        Publisher publisher = getById(id);
        if (publisher == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在", null);
        }
        
        // 检查是否有图书关联
        Long bookCount = bookMapper.countBooksByPublisher(id);
        if (bookCount != null && bookCount > 0) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "该出版社下还有图书，无法删除", null);
        }
        
        // 删除出版社
        boolean deleted = removeById(id);
        if (!deleted) {
            return Result.fail(ResultCode.FAIL.getCode(), "删除出版社失败", null);
        }
        
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> batchDeletePublishers(List<String> ids) {
        log.info("批量删除出版社，IDs：{}", ids);
        
        // 检查每个出版社是否可以删除
        for (String id : ids) {
            Publisher publisher = getById(id);
            if (publisher == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在：" + id, null);
            }
            
            // 检查是否有图书
            try {
                PublisherStatistics stats = publisherStatisticsMapper.selectByPublisherId(id);
                if (stats != null && stats.getBookCount() != null && stats.getBookCount() > 0) {
                    return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(),
                        "出版社《" + publisher.getName() + "》下还有图书，无法删除", null);
                }
            } catch (Exception e) {
                log.warn("检查出版社图书数量失败，出版社ID：{}，继续删除操作", id, e);
            }
        }
        
        // 批量删除
        boolean deleted = removeByIds(ids);
        if (!deleted) {
            return Result.fail(ResultCode.FAIL.getCode(), "批量删除出版社失败", null);
        }
        
        return Result.success();
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> enablePublisher(String id) {
        log.info("启用出版社，ID：{}", id);
        return updatePublisherStatus(id, 1);
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> disablePublisher(String id) {
        log.info("禁用出版社，ID：{}", id);
        return updatePublisherStatus(id, 0);
    }

    @Override
    @Cacheable(value = "publishers", key = "'name:' + #name")
    public List<PublisherVO> getPublishersByName(String name) {
        log.info("根据名称查询出版社，名称：{}", name);
        return publisherMapper.selectByName(name);
    }

    @Override
    @Cacheable(value = "publishers", key = "'code:' + #code")
    public PublisherVO getPublisherByCode(String code) {
        log.info("根据编码查询出版社，编码：{}", code);
        return publisherMapper.selectByCode(code);
    }

    @Override
    public List<PublisherVO> searchPublishers(String keyword, Integer limit) {
        log.info("搜索出版社，关键词：{}，限制数量：{}", keyword, limit);
        return publisherMapper.searchPublishers(keyword, limit);
    }

    @Override
    @Cacheable(value = "publishers", key = "'hot:' + #limit")
    public List<PublisherVO> getHotPublishers(Integer limit) {
        log.info("获取热门出版社，限制数量：{}", limit);
        return publisherMapper.selectHotPublishers(limit);
    }

    @Override
    @Cacheable(value = "publishers", key = "'country:' + #country")
    public List<PublisherVO> getPublishersByCountry(String country) {
        log.info("根据国家查询出版社，国家：{}", country);
        return publisherMapper.selectByCountry(country);
    }

    @Override
    @Cacheable(value = "publishers", key = "'city:' + #city")
    public List<PublisherVO> getPublishersByCity(String city) {
        log.info("根据城市查询出版社，城市：{}", city);
        return publisherMapper.selectByCity(city);
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> updatePublisherBookCount(String publisherId) {
        log.info("更新出版社图书数量，出版社ID：{}", publisherId);

        if (publisherId == null || publisherId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "出版社ID不能为空", null);
        }

        try {
            // 检查出版社是否存在
            Publisher publisher = getById(publisherId);
            if (publisher == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在", null);
            }

            // 重新计算图书数量
            int updateCount = publisherStatisticsMapper.recalculateBookCount(publisherId);
            if (updateCount > 0) {
                log.info("更新出版社图书数量成功，出版社ID：{}", publisherId);
                return Result.success();
            } else {
                log.warn("更新出版社图书数量失败，可能统计记录不存在，出版社ID：{}", publisherId);
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社统计记录不存在", null);
            }
        } catch (Exception e) {
            log.error("更新出版社图书数量失败，出版社ID：{}", publisherId, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "更新出版社图书数量失败", null);
        }
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> incrementPublisherBookCount(String publisherId) {
        log.info("增加出版社图书数量，出版社ID：{}", publisherId);
        
        int updated = publisherMapper.incrementBookCount(publisherId);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社图书数量失败", null);
        }
        
        return Result.success();
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> decrementPublisherBookCount(String publisherId) {
        log.info("减少出版社图书数量，出版社ID：{}", publisherId);
        
        int updated = publisherMapper.decrementBookCount(publisherId);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社图书数量失败", null);
        }
        
        return Result.success();
    }

    @Override
    public boolean existsByCode(String code, String excludeId) {
        return publisherMapper.existsByCode(code, excludeId);
    }

    @Override
    public boolean existsByName(String name, String excludeId) {
        return publisherMapper.existsByName(name, excludeId);
    }

    @Override
    public Result<String> importPublishers(List<PublisherCreateDTO> publishers) {
        log.info("导入出版社数据，数量：{}", publishers.size());

        if (publishers == null || publishers.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "导入数据不能为空", null);
        }

        int successCount = 0;
        int failCount = 0;
        StringBuilder errorMessages = new StringBuilder();

        for (int i = 0; i < publishers.size(); i++) {
            PublisherCreateDTO publisherDTO = publishers.get(i);
            try {
                // 数据验证
                if (publisherDTO.getName() == null || publisherDTO.getName().trim().isEmpty()) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：出版社名称不能为空；");
                    continue;
                }

                // 检查名称是否重复
                if (existsByName(publisherDTO.getName(), null)) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：出版社名称已存在；");
                    continue;
                }

                // 创建出版社
                Result<PublisherVO> createResult = createPublisher(publisherDTO);
                if (createResult.isSuccess()) {
                    successCount++;
                } else {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：").append(createResult.getMsg()).append("；");
                }
            } catch (Exception e) {
                failCount++;
                errorMessages.append("第").append(i + 1).append("行：").append(e.getMessage()).append("；");
                log.error("导入第{}行数据失败", i + 1, e);
            }
        }

        String resultMessage = String.format("导入完成，成功：%d条，失败：%d条", successCount, failCount);
        if (failCount > 0) {
            resultMessage += "。失败原因：" + errorMessages.toString();
        }

        log.info("出版社数据导入完成，成功：{}条，失败：{}条", successCount, failCount);
        return Result.success(resultMessage);
    }

    @Override
    public Result<String> exportPublishers(PublisherQuery query) {
        log.info("导出出版社数据，查询条件：{}", query);

        try {
            // 1. 查询数据
            if (query == null) {
                query = new PublisherQuery();
            }

            // 设置较大的分页大小以获取所有数据
            query.setSize(10000); // 最多导出10000条记录
            PageResult<PublisherVO> pageResult = getPublisherPage(query);

            if (pageResult == null || pageResult.getRecords() == null || pageResult.getRecords().isEmpty()) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "没有找到符合条件的出版社数据", null);
            }

            // 2. 生成Excel文件路径
            String timestamp = String.valueOf(System.currentTimeMillis());
            String fileName = "publishers_export_" + timestamp + ".xlsx";
            String filePath = "/exports/" + fileName;

            // 3. 这里应该实现实际的Excel生成逻辑
            // 由于没有具体的Excel工具类，这里只是模拟
            log.info("模拟生成Excel文件，包含{}条记录，文件路径：{}", pageResult.getRecords().size(), filePath);

            // 实际项目中，这里应该：
            // - 使用EasyExcel或Apache POI生成Excel文件
            // - 将文件保存到指定目录
            // - 返回文件的访问URL或下载链接

            String resultMessage = String.format("导出成功，共%d条记录，文件：%s",
                pageResult.getRecords().size(), fileName);

            log.info("出版社数据导出完成，记录数：{}，文件：{}", pageResult.getRecords().size(), fileName);
            return Result.success(resultMessage);

        } catch (Exception e) {
            log.error("导出出版社数据失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "导出失败：" + e.getMessage(), null);
        }
    }

    /**
     * 更新出版社状态
     */
    private Result<Void> updatePublisherStatus(String id, Integer status) {
        Publisher publisher = new Publisher();
        publisher.setId(id);
        publisher.setStatus(status);
        publisher.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(publisher);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社状态失败", null);
        }
        
        return Result.success();
    }

    /**
     * 转换为VO对象
     */
    private PublisherVO convertToVO(Publisher publisher) {
        PublisherVO publisherVO = new PublisherVO();
        BeanUtils.copyProperties(publisher, publisherVO);
        return publisherVO;
    }
}
